// main.cpp: 
//
//////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <iostream.h>
#include <fstream.h>
#include <assert.h>
#include <time.h>

#include "ssr.h"
#include "gaconfig.h"
#include "gatypes.h"
#include "garandom.h"

char *p;
void menu(void){
	cout << "Successive Survivable Routing on Mesh type networks.\n";
	cout << "This program calculate the total spare capacity/cost.\n";
	cout << "Yu Liu <yuliu@tele.pitt.edu>\n";
	cout << "Usage: " << p << " [net demo] [seed 0] [cst 0] [iter 10] [dbg 0] [help]\n\n";
	cout << "\t[net demo] or if1-8\n";
	cout << "\t[seed 0], or -1 for all 64 cases, \n\t\tor -2 for all 64 cases of SSR, SR, SPI on 8 networks.\n";
	cout << "\t[cst 0] for SSR or SR, 1 for RAFT, 2 for SPI, 3 for NS\n";
	cout << "\t[iter 10] or other number\n";
	cout << "\t[fseq 0] or 1 for increasing, -1 for decreasing in hop count\n";
	cout << "\t\t 2 for increasing -2 for decreasing in load, +-3 in both\n";
	cout << "\t[dbg 0] disable debug\n";
	cout << "\t[load 1] or 5 for none-uniform traffic load\n";
	cout << "\t[cfun 0] or 1 for non-linear link cost w(n)=3.7*n^0.67\n";
	cout << "\t[fsce 0] or 1 for node failure scenario\n";
	cout << "\t[path 0] or 1 for general path restoration; 2 for stub release; \n";
	cout << "\t\t 3 for 0 first then 1; 4 for 0 first then 2\n";
	cout << "\t[dcase 0] or 1 for all more-than-one-hop flows.\n";
	cout << "\t[multi 0] or x=1-3 for MinUx multilayer cases.\n";
	cout << "\t[prob 0.99999] or other value for single link availability.\n";
	cout << "\t[help] provide this help\n";
	cout.flush();
}
unsigned int goodseed[] = {
	1973272912, 188312339, 1072664641, 694388766,
    2009044369, 934100682, 1972392646, 1936856304,
    1598189534, 1822174485, 1871883252, 558746720,
    605846893, 1384311643, 2081634991, 1644999263,
    773370613, 358485174, 1996632795, 1000004583,
    1769370802, 1895218768, 186872697, 1859168769,
    349544396, 1996610406, 222735214, 1334983095,
    144443207, 720236707, 762772169, 437720306,
    939612284, 425414105, 1998078925, 981631283,
    1024155645, 822780843, 701857417, 960703545,
    2101442385, 2125204119, 2041095833,  89865291,
    898723423, 1859531344, 764283187, 1349341884,
    678622600, 778794064, 1319566104, 1277478588,
    538474442, 683102175, 999157082, 985046914,
    722594620, 1695858027, 1700738670, 1995749838,
    1147024708, 346983590, 565528207, 513791680 
};
	
int netmap[] = {1,6,2,3,4,5,7,8};

int main(int argc, char** argv) 
{
 
	p = strrchr(argv[0],'\\');
	if (p==NULL) 
		p = argv[0];
	else 
		p++;

	//const char *datadir = "data";
	char *netname = "t5";
	int dbg=0, cst=0, rng=0, nIter=10, fseq = 0, 
		load = 1, cfun = 0, fsce=0, pathr=0, dcase=0,multi=0;
	double prob = 0.99999; // default to five nines for link availability
	double totalCost;
	//parameter parsing
	for(int ii=1; ii<argc; ii++) {
		if (strcmp(argv[ii],"net") == 0) {
			ii++;
			assert(ii<argc);
			netname = argv[ii];
		}
		else if (strcmp(argv[ii],"dbg") == 0) {
			ii++;
			assert(ii<argc);
			dbg = atoi(argv[ii]);
		}
		else if (strcmp(argv[ii],"cst") == 0) {
			ii++;
			assert(ii<argc);
			cst = atoi(argv[ii]);
		}
		else if (strcmp(argv[ii],"seed") == 0) {
			ii++;
			assert(ii<argc);
			rng = atoi(argv[ii]);
		}
		else if (strcmp(argv[ii],"iter") == 0) {
			ii++;
			assert(ii<argc);
			nIter = atoi(argv[ii]);
			assert(nIter>0 && nIter<1000);
		}
		else if (strcmp(argv[ii],"load") == 0) {
			ii++;
			assert(ii<argc);
			load = atoi(argv[ii]);
			assert(load>0 && load<1000);
		}
		else if (strcmp(argv[ii],"fseq") == 0) {
			ii++;
			assert(ii<argc);
			fseq = atoi(argv[ii]);;
			assert(fseq>=-4 && fseq<=4);
		}
		else if (strcmp(argv[ii],"cfun") == 0) {
			ii++;
			assert(ii<argc);
			cfun = atoi(argv[ii]);
			assert(cfun>=0 && cfun<2);
		}
		else if (strcmp(argv[ii],"fsce") == 0) {
			ii++;
			assert(ii<argc);
			fsce = atoi(argv[ii]);
			assert(fsce>=0 && fsce<2);
		}
		else if (strcmp(argv[ii],"path") == 0) {
			ii++;
			assert(ii<argc);
			pathr = atoi(argv[ii]);
			// FD path restoration can not cooperate with NS
			if (pathr !=0 && cst == 3) 
				cst = 0;  	
			assert(pathr>=0 && pathr<5);
		}
		else if (strcmp(argv[ii],"dcase") == 0) {
			ii++;
			assert(ii<argc);
			dcase = atoi(argv[ii]);
			assert(dcase>=0 && dcase<2);
		}
		else if (strcmp(argv[ii],"multi") == 0) {
			ii++;
			assert(ii<argc);
			multi = atoi(argv[ii]);
			assert(multi>=0 && multi<=3);
		}
		else if (strcmp(argv[ii],"prob") == 0) {
			ii++;
			assert(ii<argc);
			prob = atoi(argv[ii]);
			assert(prob>0 && prob<1);
		}
		else if (strcmp(argv[ii],"help") == 0) {
			menu();
			exit(0);
		}

    }

	ssr * net ;
	if (rng >=0) {
		net = new ssr(netname, dbg, cst, nIter, 
				load, fseq, cfun,fsce,pathr,dcase,multi, prob);
		
		if ( net->listdfs() != 2)
			return 1;
		//rng %= 64;
		cout << "Random seed No."<<rng<< "\n";//" ="<<goodseed[rng]<<endl;
		if (rng <64)
			GARandomSeed(goodseed[rng]);
		else
			GARandomSeed(goodseed[rng]+29*rng);  // allow more than 64 seeds
		net->fout = 1;  // generate output files
		clock_t start, finish;
		int work = net->allworking();  // find working paths
		net->writeworkdat();
		
		start = clock();
		int spare = net->global(&totalCost); 
		net->writesparedat();
		net->writealltxt();
		finish = clock();
		cout << work << "\t" << spare << endl;
		
		double avg_prob = net->comp_availability ();
		cout << avg_prob << endl;

		double duration = (double)(finish - start) / CLOCKS_PER_SEC;
		printf( "%2.2f seconds\n", duration );
		cout << endl;
		return 0;
	} else if (rng == -1) {
		int rst[3][64];
		int bestsd = -1;
		double rcost[3][64];
		int maxrst, minrst;
		double mincst, maxcst;
		net = new ssr(netname, dbg, cst, nIter,load,fseq, 
				cfun,fsce,pathr,dcase,multi, prob);
		maxrst = net->allworking();
		cout << maxrst <<"\t";

		clock_t start, finish;
		maxrst=0; minrst=100000; 
		maxcst=0.0; mincst=1000000.0; 
		start = clock();
		for (rng=0; rng <64; rng++){
			//cout << rng <<" ";cout.flush();
			GARandomSeed(goodseed[rng]);
			net->init(); // disable file output
			rst[0][rng] = net->global(&totalCost);
			rcost[0][rng] = totalCost;
			if (cfun == 0){
				if (minrst>rst[0][rng]){
					minrst = rst[0][rng];
					bestsd = rng;
				}
				if (maxrst<rst[0][rng]) {
					maxrst = rst[0][rng];
				}
				mincst = min(mincst, rcost[0][rng]);
				maxcst = max(maxcst, rcost[0][rng]);
			} else {
				if (mincst>rcost[0][rng]){
					mincst = rcost[0][rng];
					bestsd = rng;
				}
				if (maxcst<rcost[0][rng]) {
					maxcst = rcost[0][rng];
				}
				minrst = min(minrst, rst[0][rng]);
				maxrst = max(maxrst, rst[0][rng]);
			}
		}
		finish = clock();
		double duration = (double)(finish - start) / CLOCKS_PER_SEC;
		printf( "%2.2f seconds\n", duration );
		cout << bestsd << "\t";
		cout << minrst << " " << maxrst << "\t";
		cout << mincst << " " << maxcst << "\t";
		delete net;
		cout << endl;
		return 0;
	} 

	int rst[8][3][64];
	int maxrst, minrst,i;
	for (int n=0; n<8; n++){
		sprintf(netname,"if%1d",netmap[n]);
		cout << netmap[n]; cout.flush();
		// SSR
		net = new ssr(netname, 0, 0, 20, load,fseq, 
				cfun,fsce,pathr,dcase,multi, prob);
		maxrst = net->allworking();
		//cout << maxrst <<"\t";;
		//clock_t start, finish;
		net->allworking();  // find working paths
		//start = clock();
		maxrst=0, minrst=10000;
		for (rng=0; rng <64; rng++){
			GARandomSeed(goodseed[rng]);
			net->init(); // disable file output
			rst[n][0][rng] = net->global(&totalCost);
			minrst = min(minrst,rst[n][0][rng]);
			maxrst = max(maxrst,rst[n][0][rng]);
		}
		//finish = clock();
		cout << ",";//minrst << " " << maxrst << "\t";
		//double duration = (double)(finish - start) / CLOCKS_PER_SEC;
		//printf( "%2.1f seconds\n", duration );
		cout.flush();
		delete net;

		// SR or SCI
		net = new ssr(netname, 0, 0, 1, load, fseq, 
				cfun,fsce,pathr,dcase,multi,
				prob); //dbg, cst, nIter);
		net->allworking();
		maxrst=0, minrst=10000;
		for (rng=0; rng <64; rng++){
			GARandomSeed(goodseed[rng]);
			net->init(); // disable file output
			rst[n][1][rng] = net->global(&totalCost);
			minrst = min(minrst,rst[n][1][rng]);
			maxrst = max(maxrst,rst[n][1][rng]);
		}
		//finish = clock();
		cout << ",";//minrst << " " << maxrst <<"\t";
		cout.flush();
		delete net;

		// SPI
		net = new ssr(netname, 0, 4, 20, load,fseq, 
				cfun,fsce,pathr,dcase,multi,
				prob);
		net->allworking();
		maxrst=0, minrst=10000;
		for (rng=0; rng <64; rng++){
			GARandomSeed(goodseed[rng]);
			net->init(); // disable file output
			rst[n][2][rng] = net->global(&totalCost);
			minrst = min(minrst,rst[n][2][rng]);
			maxrst = max(maxrst,rst[n][2][rng]);
		}
		//finish = clock();
		cout << ",\t";//minrst << " " << maxrst <<"\t";
		cout.flush();
		delete net;
		/* donot generate RAFT results
		nIter = 1; cst = 1;
		net = new ssr(netname, 0, 1, 2, load,fseq);
		net->allworking();
		net->init(); // disable file output
		minrst = net->global(&totalCost);
		//finish = clock();
		cout << ",\t"; //minrst << " " << endl;
		cout.flush();
		delete net;
		*/
	}
	cout <<endl;

	// output 
	for (rng=0; rng <64; rng++){
		for (int n=0;n<8; n++){
			for (i=0;i<3;i++)
				cout << rst[n][i][rng] << ",";
			cout << " " ;
		}
		cout << endl;
	}
		cout << endl;
	cout.flush();	

	return 0;
}

